﻿using KalevaAalto.DataPart.DataBasePart.Attributes;
using KalevaAalto.DataPart.Excel.Models;
using KalevaAalto.DataPart.Models;
using Npgsql.TypeHandlers.NetworkHandlers;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace KalevaAalto.DataPart.Excel.Base
{
    public abstract class BaseWorksheets : IEnumerable<BaseWorksheet>
    {
        private BaseWorkbook _workbook;
        public BaseWorksheets(BaseWorkbook workbook) { _workbook = workbook; }
        public abstract BaseWorksheet this[int index] { get; }
        public abstract BaseWorksheet this[string worksheetName] { get; }

        public abstract bool Remove(string worksheetName);

        public abstract BaseWorksheet Add(string worksheetName);

        public abstract IEnumerator<BaseWorksheet> GetEnumerator();
        
        public BaseWorkbook Workbook => _workbook;
        IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();






        #region 添加数据表

        /// <summary>
        /// 设置字段所在行格式
        /// </summary>
        /// <param name="worksheet">工作表</param>
        /// <param name="titleRow">字段所在行</param>
        /// <param name="serCol">初始列</param>
        /// <param name="columnCount">列数</param>
        public static void SetWorksheetTitleStyle(BaseWorksheet worksheet,int titleRow,int serCol,int columnCount)
        {
            columnCount = System.Math.Max(columnCount, 1);
            var rng = worksheet.Cells[titleRow, serCol, titleRow, serCol + columnCount - 1];
            rng!.Style.Prase(new Style { FontWeight = Enums.FontWeight.Bolder, FontName = @"黑体", WrapText = true });
        }




        public BaseWorksheet Add(DataTable dataTable, IEnumerable<DataColumnAttribute>? dataColumnStyles = null, string tableName = EmptyString)
        {
            if (string.IsNullOrEmpty(tableName))
            {
                tableName = dataTable.TableName;
            }
            if (string.IsNullOrEmpty(tableName))
            {
                tableName = GetNewColumnName(@"Sheet0", this.Select(it => it.Name));
            }
            BaseWorksheet worksheet = Add(tableName);

            int titleRow = 1;
            int startRow = titleRow + 1;
            int serCol = 1;
            int rowCout = dataTable.Rows.Count;
            int columnCount = dataTable.Columns.Count;
            BaseRange rng;


            var dataColumnStyleDic = DataColumnAttribute
                .GetDataColumnStyles(dataTable, dataColumnStyles)
                .ToImmutableDictionary(it => it.ColumnName, it => it);

            SetWorksheetTitleStyle(worksheet,titleRow,serCol,columnCount);

            if(rowCout > 0)
            {
                for (int column = 0; column < columnCount; column++)
                {
                    string columnName = dataTable.Columns[column].ColumnName;
                    worksheet.Cells[titleRow, serCol + column]!.Value = columnName;
                    DataColumnAttribute dataColumnStyle = dataColumnStyleDic[columnName];
                    rng = worksheet.Cells[startRow, serCol + column, titleRow + rowCout, serCol + column]!;

                    rng.Columns.Width = dataColumnStyle.Width;
                    rng.Style.Prase(dataColumnStyle);


                }

                for (int row = 0; row < rowCout; row++)
                {
                    for (int column = 0; column < columnCount; column++)
                    {
                        var cell = worksheet.Cells[startRow + row, serCol + column];
                        cell!.Value = dataTable.Rows[row][column];
                        string columnName = dataTable.Columns[column].ColumnName;
                        DataColumnAttribute dataColumnStyle = dataColumnStyleDic[columnName];
                    }
                }
            }

            


            worksheet.Range.SetTable();
            worksheet.Range.Style.BorderStyle = Enums.BorderStyle.Thin;
            worksheet.View.ShowGridLines = false;


            return worksheet;
        }



        public BaseWorksheet Add<T>(IEnumerable<T> objEnumerable,
            IEnumerable<DataColumnAttribute>? dataColumnStyles = null,
            IEnumerable<string>? selectColumnNames =null,
            string tableName = EmptyString) 
        {
            if (string.IsNullOrEmpty(tableName))
            {
                tableName = GetTableName<T>(tableName);
            }
            BaseWorksheet worksheet = Add(tableName);
            IDictionary<string, PropertyInfo> columnInfos = GetColumnInfoDic(typeof(T), selectColumnNames);
            
            var columnNames = columnInfos.Keys.ToList();
            var properties = columnInfos.Values.ToList();
            var objs = objEnumerable.ToArray();

            int titleRow = 1;
            int startRow = titleRow + 1;
            int serCol = 1;
            int rowCout = objs.Length;
            int columnCount = columnInfos.Count;
            BaseRange rng;


            var dataColumnStyleDic = DataColumnAttribute
                .GetDataColumnStyles(typeof(T), dataColumnStyles)
                .ToImmutableDictionary(it => it.ColumnName, it => it);


            SetWorksheetTitleStyle(worksheet, titleRow, serCol, columnCount);


            for (int column = 0; column < columnCount; column++)
            {
                string columnName = columnNames[column];
                worksheet.Cells[titleRow, serCol + column]!.Value = columnName;
                DataColumnAttribute dataColumnStyle = dataColumnStyleDic[columnName];
                rng = worksheet.Cells[startRow, serCol + column, titleRow + System.Math.Max(rowCout,1), serCol + column]!;

                rng.Columns.Width = dataColumnStyle.Width;
                rng.Style.Prase(dataColumnStyle);
            }

            for (int row = 0; row < rowCout; row++)
            {
                for (int column = 0; column < columnCount; column++)
                {
                    worksheet.Cells[startRow + row, serCol + column]!.Value = properties[column].GetValue(objs[row]);


                    var cell = worksheet.Cells[startRow + row, serCol + column]!;
                    cell.Value = properties[column].GetValue(objs[row]);
                    string columnName = columnNames[column];
                    DataColumnAttribute dataColumnStyle = dataColumnStyleDic[columnName];
                }
            }


            worksheet.Range.SetTable();
            worksheet.Range.Style.BorderStyle = Enums.BorderStyle.Thin;
            worksheet.View.ShowGridLines = false;


            return worksheet;
        }




        #endregion
    }
}
